#include "thread_intf.h"
#include "log_intf.h"
#include "lvos.h"
#include "utlist.h"

#define MAX_THREADS 10

typedef struct TagPThreadTask {
    void (*func)(void*);
    void* ctx;
    struct TagPThreadTask *prev;
    struct TagPThreadTask *next;
} PThreadTask;

typedef struct TPool {
    pthread_t threads[MAX_THREADS];
    PThreadTask *queue;
    int queue_size;
    int shutdown;
    pthread_mutex_t lock;
    uint32_t thread_count;
} TPool;

void WorkThread(void* arg) {
    TPool* pool = (TPool*)arg;
    PThreadTask *task = NULL;
    void (*func)(void *ctx) = NULL;
    void *ctx = NULL;


    while(True) {
        pthread_mutex_lock(&pool->lock);
        if(pool->shutdown) {
            pthread_mutex_unlock(&pool->lock);
            pthread_exit(NULL);
        }
        if (pool->queue_size == 0) {
            pthread_mutex_unlock(&pool->lock);
            usleep(1000);
            continue;
        }

        task = pool->queue;
        DL_DELETE(pool->queue, task);
        pool->queue_size--;
        func = task->func;
        ctx = task->ctx;
        pthread_mutex_unlock(&pool->lock);
        free(task);
        func(ctx);
    }
    return NULL;
}

int32_t CreatePThreadPool(TPool** ppPool, uint32_t threadCount) {
    if(threadCount < 1 || threadCount > MAX_THREADS) {
        LOG_ERROR("Invalid thread count %u (must be 1-%d)", threadCount, MAX_THREADS);
        return RETURN_ERROR;
    }

    TPool* pool = (TPool*)malloc(sizeof(TPool));
    if(pool == NULL) {
        LOG_ERROR("Failed to allocate memory for thread pool");
        return RETURN_ERROR;
    }

    memset(pool, 0, sizeof(TPool));
    pool->thread_count = threadCount;

    if(pthread_mutex_init(&pool->lock, NULL) != 0) {
        LOG_ERROR("Failed to initialize mutex");
        free(pool);
        return RETURN_ERROR;
    }

    for(uint32_t i = 0; i < threadCount; i++) {
        if(pthread_create(&pool->threads[i], NULL, WorkThread, pool) != 0) {
            LOG_ERROR("Failed to create worker thread %u", i);
            pool->shutdown = 1;
            ThreadPoolDestroy(pool);
            return RETURN_ERROR;
        }
    }

    *ppPool = pool;
    LOG_INFO("PThreadPool: Create TPool Success, count(%u)", threadCount);
    return RETURN_OK;
}

int32_t ThreadPoolAddTask(TPool* pool, void (*func)(void*), void* ctx) {
    if(pool == NULL || func == NULL) {
        LOG_ERROR("Invalid arguments");
        return RETURN_ERROR;
    }

    PThreadTask *task = (PThreadTask*)malloc(sizeof(PThreadTask));
    if(task == NULL) {
        LOG_ERROR("Failed to allocate memory for task");
        return RETURN_ERROR;
    }

    task->func = func;
    task->ctx = ctx;

    pthread_mutex_lock(&pool->lock);
    DL_APPEND(pool->queue, task);
    pool->queue_size++;
    pthread_mutex_unlock(&pool->lock);
    LOG_INFO("ThreadPool: Add Task To Pool Success");
    return RETURN_OK;
}

void ThreadPoolDestroy(TPool* pool) {
    if(pool == NULL) return;

    pthread_mutex_lock(&pool->lock);
    pool->shutdown = 1;
    pthread_mutex_unlock(&pool->lock);


    PThreadTask *task, *tmp;
    DL_FOREACH_SAFE(pool->queue, task, tmp) {
        DL_DELETE(pool->queue, task);
        free(task);
    }

    pthread_mutex_destroy(&pool->lock);
    LOG_INFO("PThreadPool: Free TPool success, count(%u)", pool->thread_count);
    free(pool);
}
